# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'

import os
import logging

Logger = logging.getLogger('PySolFC.Games_MAHJONGG')

from pysollib.utillib.misc import kwdefault
from pysollib.packlib.info import TYPE_MAHJONGG
from pysollib.gamelib import info as gi

GT, SL = gi.GT, gi.SL

__PULUGINS_DIR = os.path.dirname(os.path.realpath(__file__))
__PULUGINS_MOD = 'pysollib.games.mahjongg.%s'


def comp_cardset(ncards):
    """
    Calculate the needed part of the tile sets needed to produce a set with
    ncards. Each tile set has 4 sets of 3 suits of 9 tiles, 4 sets of 7 honors
    3 of which are placed as the 10th card in each suit and 4 are the 1st 4
    trump. The remaining trumps are bonus tiles which only have 1 set.

    :returns: decks / 4, ranks, honors, bonus
    """
    assert ncards % 4 == 0
    assert 0 < ncards <= 288  # 2 set max
    decks = 1
    cards = ncards // 4  # Mahjongg has 4 sets for each suit rank and honors
    if ncards > 144:
        assert ncards % 8 == 0
        decks = 2
        cards = cards // 2
    ranks, trumps = divmod(cards, 3)  # Only 3 suits in a Mahjongg tile set
    if ranks > 10:  # Too many ranks... need 9 + honors for dragons
        trumps += (ranks - 10) * 3
        ranks = 10
    if trumps > 4:  # Include bonus tiles Flowers and Seasons
        trumps = 4 + (trumps - 4) * 4
    assert 0 <= ranks <= 10 and 0 <= trumps <= 12
    bonus = max(0, trumps - min(4, trumps))  # Deduct honors from trumps
    trumps -= bonus  # Deduct bonus from trumps
    return decks, ranks, trumps, bonus


def _parseinfo(game):
    """
    _parseinfo(game) -> dict

    Check the `__info__` special attribute of `game` and default ranks and
    suits for a Mahjongg deck in preparation for adding to the game database.


    :note: `gameinfo['decks']` value will be *4 actually.
      `gameinfo['si']['decks']` contains the actual num of tile sets.

    :raises: AssertionError when `__layout__` is missing or empty.
    """
    assert hasattr(game, '__layout__') and game.__layout__
    info = game.__info__
    info['gameclass'] = game
    ncards = info.get('ncards', 144)
    if 'ncards' in info:
        del info['ncards']
    decks, ranks, trumps, bonus = comp_cardset(ncards)
    kwdefault(info, name='Mahjongg {}'.format(info['short_name']),
                    category=TYPE_MAHJONGG, game_type=(GT.MAHJONGG |
                    info.get('game_type', 0)), skill_level=SL.MOSTLY_SKILL,
                    decks=decks * 4, bonus=range(bonus),
                    suits=range(3), ranks=range(ranks), trumps=range(trumps),
                    si={'decks': decks, 'ncards': ncards})
    return info


def loadgames():
    """
    loadgames() -> None

    Load games found in `PROVIDES` in each module not starting with `_`.
    """
    for filename in os.listdir(__PULUGINS_DIR):
        if filename.endswith('.py') and not filename.startswith('_'):
            module = __PULUGINS_MOD % filename[:-3]
            Logger.info('Loading: %s', module)
            try:
                gp = __import__(module, None, None, [''])
            except NameError as ex:
                Logger.warning('Error loading %s: %s', filename[:-3], ex)
                continue
            if not hasattr(gp, 'PROVIDES'):
                continue
            for game in gp.PROVIDES:
                yield(_parseinfo(game))